package com.zh.harmony.livedata;

import com.zh.harmony.arch.core.executor.ArchTaskExecutor;
import com.zh.harmony.arch.core.internal.SafeIterableMap;
import com.zh.harmony.lifecycle.GenericLifecycleObserver;
import com.zh.harmony.lifecycle.Lifecycle;
import com.zh.harmony.lifecycle.LifecycleOwner;

import java.util.Iterator;
import java.util.Map;

/**
 * LiveData
 */
public abstract class LiveData<T> {
    /**
     * 同步锁
     */
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    final Object mDataLock = new Object();
    /**
     * 起始版本
     */
    static final int START_VERSION = -1;
    /**
     * LiveData没有设置值时的默认值
     */
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    static final Object NOT_SET = new Object();
    /**
     * 观察者集合
     */
    private final SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();
    /**
     * 记录有多少个观察者处于活动状态
     */
    // how many observers are in active state
    @SuppressWarnings("WeakerAccess") /* synthetic access */
            int mActiveCount = 0;
    /**
     * LiveData的数据
     */
    private volatile Object mData;
    // when setData is called, we set the pending data and actual data swap happens on the main
    // thread
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    volatile Object mPendingData = NOT_SET;
    /**
     * LiveData的数据版本
     */
    private int mVersion;
    /**
     * 是否正在派发更新中
     */
    private boolean mDispatchingValue;
    @SuppressWarnings("FieldCanBeLocal")
    private boolean mDispatchInvalidated;
    /**
     * PostValue时，在主线程中更新Value的Runnable
     */
    private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                //拿取要设置的值
                newValue = mPendingData;
                //恢复mPendingData为默认值
                mPendingData = NOT_SET;
            }
            //更新
            setValue((T) newValue);
        }
    };

    /**
     * 指定某个值来创建LiveData
     */
    public LiveData(T value) {
        mData = value;
        mVersion = START_VERSION + 1;
    }

    /**
     * 创建一个没有赋值的LiveData
     */
    public LiveData() {
        mData = NOT_SET;
        mVersion = START_VERSION;
    }

    /**
     * 通知观察者，如果观察者不是活跃状态，不进行通知
     */
    @SuppressWarnings("unchecked")
    private void considerNotify(ObserverWrapper observer) {
        //不活跃，不通知
        if (!observer.mActive) {
            return;
        }
        //二次确认是否为不活跃，因为可能生命周期发生了变化，但mActive标记还未更新
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        //已经更新过了，不更新
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        //更新版本
        observer.mLastVersion = mVersion;
        //回调监听的观察者
        observer.mObserver.onChanged((T) mData);
    }

    /**
     * 派发更新
     *
     * @param initiator 派发给指定的观察者，如果为null，则派发给所有观察者
     */
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(ObserverWrapper initiator) {
        //正在派发中，设置为派发失效标志
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        //设置正在派发中
        mDispatchingValue = true;
        do {
            //设置失效标记为false
            mDispatchInvalidated = false;
            //有指定观察者，那么只派发给它
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                //没有指定，派发给所有观察者
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                     mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    //派发过程中，数据发生了变化，跳出循环，因为mDispatchInvalidated为true，则会重新遍历
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);//当在派发过程中，数据改变时，标记为true
        //设置没有派发
        mDispatchingValue = false;
    }

    /**
     * 添加观察者，在生命周期销毁时，自动注销
     *
     * @param owner    要绑定的Lifecycle
     * @param observer 观察者
     */
    public void observe(LifecycleOwner owner, Observer<? super T> observer) {
        //检查是否是主线程，不是则抛异常
        assertMainThread("observe");
        //如果页面已经销毁了，不添加
        if (owner.getLifeCycle().getCurrentState() == Lifecycle.State.DESTROYED) {
            //ignore
            return;
        }
        //包装观察者
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //查找是否添加过了，如果已经添加过，则返回之前添加的观察者
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //存在重复添加，抛异常
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        //再次判断是否添加
        if (existing != null) {
            return;
        }
        //设置生命周期观察
        owner.getLifeCycle().addObserver(wrapper);
    }

    /**
     * 永久观察，需要自己注销
     */
    public void observeForever(Observer<? super T> observer) {
        //检查是否是主线程，不是则抛异常
        assertMainThread("observeForever");
        //包装观察者
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        //判断是否重复添加
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        //设置活跃
        wrapper.activeStateChanged(true);
    }

    /**
     * 移除观察
     */
    public void removeObserver(final Observer<? super T> observer) {
        assertMainThread("removeObserver");
        ObserverWrapper removed = mObservers.remove(observer);
        if (removed == null) {
            return;
        }
        removed.detachObserver();
        //取消活跃
        removed.activeStateChanged(false);
    }

    /**
     * 移除指定页面类上的所有观察者
     */
    @SuppressWarnings("WeakerAccess")
    public void removeObservers(final LifecycleOwner owner) {
        //检查是否是主线程，不是则抛异常
        assertMainThread("removeObservers");
        for (Map.Entry<Observer<? super T>, ObserverWrapper> entry : mObservers) {
            //遍历这个LiveData的观察者，如果绑定的是传进来的LifecycleOwner，则移除
            if (entry.getValue().isAttachedTo(owner)) {
                removeObserver(entry.getKey());
            }
        }
    }

    /**
     * 非主线程中更新值，会转发到主线程后更新
     * 注意：只有最后一次更新生效
     */
    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            //如果设置的值是默认值，不更新
            postTask = mPendingData == NOT_SET;
            //把要更新的值，转移到mPendingData
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        //转发到主线程执行
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

    /**
     * 更新值，必须在主线程更新，如果需要在子线程更新，请使用 postValue
     */
    protected void setValue(T value) {
        //检查是否是主线程，不是则抛异常
        assertMainThread("setValue");
        //更新版本
        mVersion++;
        //更新值
        mData = value;
        //通知观察者更新
        dispatchingValue(null);
    }

    /**
     * 获取当前值
     */
    @SuppressWarnings("unchecked")
    public T getValue() {
        Object data = mData;
        //如果没有设置过，则返回null
        if (data != NOT_SET) {
            return (T) data;
        }
        return null;
    }

    /**
     * 获取版本
     */
    int getVersion() {
        return mVersion;
    }

    /**
     * 至少有一个观察者的状态变成活跃
     */
    protected void onActive() {
    }

    /**
     * 没有一个观察者活跃
     */
    protected void onInactive() {
    }

    /**
     * 如果这个LiveData有观察者，则返回true
     */
    @SuppressWarnings("WeakerAccess")
    public boolean hasObservers() {
        return mObservers.size() > 0;
    }

    /**
     * 如果这个LiveData有活跃的观察则，则返回true
     */
    @SuppressWarnings("WeakerAccess")
    public boolean hasActiveObservers() {
        return mActiveCount > 0;
    }

    /**
     * 有Lifecycle绑定的观察者
     */
    class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        final LifecycleOwner mOwner;

        LifecycleBoundObserver(LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }

        @Override
        boolean shouldBeActive() {
            //onStart()之后，onStop()之前为活跃，就是onStart()`、`onResume()`、`onPause()这3个生命周期内时
            return mOwner.getLifeCycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED);
        }

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            //生命周期变为销毁时，自动移除观察者
            if (mOwner.getLifeCycle().getCurrentState() == Lifecycle.State.DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }

        @Override
        void detachObserver() {
            mOwner.getLifeCycle().removeObserver(this);
        }
    }

    /**
     * 观察者装饰器，提供一个公共方法
     */
    private abstract class ObserverWrapper {
        /**
         * 包装的观察者
         */
        final Observer<? super T> mObserver;
        /**
         * 是否活跃，不活跃时不进行派发
         */
        boolean mActive;
        /**
         * 当前数据的版本号
         */
        int mLastVersion = START_VERSION;

        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }

        /**
         * 返回当前是否是活跃状态
         */
        abstract boolean shouldBeActive();

        /**
         * 是否绑定了指定的LifecycleOwner
         */
        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        /**
         * 移除生命周期监听
         */
        void detachObserver() {
        }

        /**
         * 活跃或非活跃时回调
         */
        void activeStateChanged(boolean newActive) {
            //状态没有变化，直接返回
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            //是否不活跃
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            //更新活跃数量，活跃+1，不活跃-1
            LiveData.this.mActiveCount += (mActive ? 1 : -1);
            //活跃状态的观察者数量，从0 -> 1时，回调onActive()
            if (wasInactive && mActive) {
                onActive();
            }
            //不活跃状态的观察者数量，从1 -> 0时，回调onInactive()
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            //观察者，从不活跃变化为活跃时，派发当前值
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

    /**
     * 永久活跃的观察者
     */
    private class AlwaysActiveObserver extends ObserverWrapper {
        AlwaysActiveObserver(Observer<? super T> observer) {
            super(observer);
        }

        @Override
        boolean shouldBeActive() {
            //一直都是活跃的，所以无论观察者是否活跃都派发更新
            return true;
        }
    }

    /**
     * 检查是否是主线程，如果不是抛异常
     */
    static void assertMainThread(String methodName) {
        if (!ArchTaskExecutor.getInstance().isMainThread()) {
            throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                    + " thread");
        }
    }
}